package com.coincalf.admin.web.funds.account;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.coincalf.admin.annotation.Log;
import com.coincalf.admin.common.ResultMap;
import com.coincalf.admin.dto.AccountDTO;
import com.coincalf.admin.entity.Account;
import com.coincalf.admin.entity.SysUser;
import com.coincalf.admin.enums.SysLogTypeEnum;
import com.coincalf.admin.service.AccountService;
import com.coincalf.admin.view.ReportCsvUtils;
import com.coincalf.framework.enums.BusinessType;
import com.coincalf.framework.exception.AccountException;
import com.google.common.base.Strings;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;
import org.supercsv.cellprocessor.CellProcessorAdaptor;
import org.supercsv.cellprocessor.ift.CellProcessor;
import org.supercsv.util.CsvContext;
import springfox.documentation.annotations.ApiIgnore;
import javax.servlet.http.HttpServletResponse;

/**
 * <p>
 * 账户资金记录 前端控制器
 * </p>
 *
 * @author Haliyo
 * @since 2018-05-13
 */
@Slf4j
@RestController
@RequestMapping("/account")
@Api(value = "资金账户记录", description = "账户资金管理")
public class AccountController {

    @Autowired
    private AccountService accountService;
    @PreAuthorize("hasAuthority('account_query')")
    @Log(value = "查询账户资金列表",type = SysLogTypeEnum.SELECT)
    @GetMapping
    @ApiImplicitParams({
            @ApiImplicitParam(name = "size", value = "每页显示条数，默认 10", required = false, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "current", value = "当前页", required = false, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "coinId", value = "币种ID", required = false, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "userId", value = "用户ID", required = false, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "userName", value = "真实姓名", required = false, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "mobile", value = "手机号", required = false, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "recAddr", value = "钱包地址", required = false, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "status", value = "状态:1正常 2冻结", required = false, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "startAmount", value = "起始金额", required = false, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "endAmount", value = "结束金额", required = false, dataType = "String", paramType = "query"),
    })
    @ApiOperation(authorizations = {@Authorization(value="Authorization")},value = "按条件分页查询账户资金列表" ,httpMethod = "GET")
    public Object selectPage(@ApiIgnore Page<Account> page,
                             String coinId,String userId,
                             String userName,String mobile,
                             String recAddr,String status,
                             String startAmount,String endAmount) {
        EntityWrapper<Account> ew = new EntityWrapper<>();
        if (!Strings.isNullOrEmpty(coinId)) {
            ew.eq("coin_id", coinId);
        }
        if (!Strings.isNullOrEmpty(userId)) {
            ew.eq("user_id", userId);
        }
        if (!Strings.isNullOrEmpty(userName)) {
            ew.like("username", userName);
        }
        if(!Strings.isNullOrEmpty(mobile)){
            ew.like("mobile",mobile);
        }
        if(!Strings.isNullOrEmpty(recAddr)){
            ew.eq("rec_addr",recAddr);
        }
        if(!Strings.isNullOrEmpty(status)){
            ew.where("a.status = {0}",status);
        }
        if(!Strings.isNullOrEmpty(startAmount)){
            ew.ge("balance_amount",startAmount);
        }
        if(!Strings.isNullOrEmpty(endAmount)){
            ew.le("balance_amount",endAmount);
        }
        return ResultMap.getSuccessfulResult(accountService.selectListPage(page, ew));
    }

    @Log(value = "资金状态设置",type = SysLogTypeEnum.UPDATE)
    @PreAuthorize("hasAuthority('account_status_update')")
    @PostMapping
    @ApiOperation(authorizations = {@Authorization(value="Authorization")},value = "资金状态设置(status:1解冻 2冻结)")
    @RequestMapping(path = "/setStatus",method = RequestMethod.POST)
    public Object setStatus(@RequestBody Account account) {
        Account oriAccount = accountService.selectById(account.getId());
        if(null == oriAccount){
            return ResultMap.getFailureResult("该记录不存在!");
        }

        if(oriAccount.getStatus() > 2
                || oriAccount.getStatus() < 1
                || oriAccount.getStatus() == null){
            return ResultMap.getFailureResult("输入参数有误!");
        }

        if(oriAccount.getStatus().equals(account.getStatus())){
            return ResultMap.getFailureResult("当前状态不能执行此操作!");
        }
        Account newAccount = new Account();
        newAccount.setId(account.getId());
        newAccount.setStatus(account.getStatus());
        //乐观锁更新
        newAccount.setVersion(oriAccount.getVersion());
        if(accountService.updateById(newAccount)){
            return ResultMap.getSuccessfulResult("操作成功!");
        }else {
            return ResultMap.getFailureResult("操作失败!");
        }
    }

    @Log(value = "账户资金导出",type = SysLogTypeEnum.EXPORT)
    @PreAuthorize("hasAuthority('account_export')")
    @RequestMapping({"/exportList"})
    @ResponseBody
    @ApiOperation(authorizations = {@Authorization(value="Authorization")},value = "账户资金导出", notes = "账户资金导出",httpMethod = "GET")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "coinId", value = "币种ID", required = false, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "userId", value = "用户ID", required = false, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "userName", value = "真实姓名", required = false, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "mobile", value = "手机号", required = false, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "recAddr", value = "钱包地址", required = false, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "status", value = "状态:1正常 2冻结", required = false, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "startAmount", value = "起始金额", required = false, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "endAmount", value = "结束金额", required = false, dataType = "String", paramType = "query"),
    })
    public void export(@ApiIgnore Page<Account> page,
                               String coinId, String userId,
                               String userName, String mobile,
                               String recAddr, String status,
                               String startAmount, String endAmount
                            , HttpServletResponse response) throws Exception {
        EntityWrapper<Account> ew = new EntityWrapper<>();
        if (!Strings.isNullOrEmpty(coinId)) {
            ew.eq("coin_id", coinId);
        }
        if (!Strings.isNullOrEmpty(userId)) {
            ew.eq("user_id", userId);
        }
        if (!Strings.isNullOrEmpty(userName)) {
            ew.like("username", userName);
        }
        if(!Strings.isNullOrEmpty(mobile)){
            ew.like("mobile",mobile);
        }
        if(!Strings.isNullOrEmpty(recAddr)){
            ew.eq("rec_addr",recAddr);
        }
        if(!Strings.isNullOrEmpty(status)){
            ew.where("a.status = {0}",status);
        }
        if(!Strings.isNullOrEmpty(startAmount)){
            ew.ge("balance_amount",startAmount);
        }
        if(!Strings.isNullOrEmpty(endAmount)){
            ew.le("balance_amount",endAmount);
        }
        page.setCurrent(1);
        page.setSize(100000);//限制导出数量10W
        Page<Account> retPage = accountService.selectListPage(page, ew);
        String[] header = {"ID","用户ID" ,"用户名","真实姓名", "币种名称","手机号码",  "账户余额", "冻结金额","钱包地址","总充值","总提现","状态"};
        String[] properties = {"idStr","userId", "userName","realName",  "coinName","mobile", "balanceAmountStr", "freezeAmountStr","recAddr","rechargeAmountStr","withdrawalsAmountStr","statusStr"};
        CellProcessor[] PROCESSORS = new CellProcessor[] {
                null,
                new CellProcessorAdaptor() {
                    @Override
                    public String execute(Object value, CsvContext context) {
                        String v ="\t"+String.valueOf(value);
                        return v;
                    }
                },
                null,
                null,
                null,
                null,
                new CellProcessorAdaptor() {
                    @Override
                    public String execute(Object value, CsvContext context) {
                        String v ="\t"+String.valueOf(value);
                        return v;
                    }
                },
                new CellProcessorAdaptor() {
                    @Override
                    public String execute(Object value, CsvContext context) {
                        String v ="\t"+String.valueOf(value);
                        return v;
                    }
                },
                null,
                new CellProcessorAdaptor() {
                    @Override
                    public String execute(Object value, CsvContext context) {
                        String v ="\t"+String.valueOf(value);
                        return v;
                    }
                },
                new CellProcessorAdaptor() {
                    @Override
                    public String execute(Object value, CsvContext context) {
                        String v ="\t"+String.valueOf(value);
                        return v;
                    }
                },
                null
        };
        String fileName="账户资金.csv";
        try {
            ReportCsvUtils.reportListCsv(response,header,properties,fileName, retPage.getRecords(),PROCESSORS);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Log(value = "查询用户的钱包地址",type = SysLogTypeEnum.SELECT)
    @GetMapping
    @ApiImplicitParams({
            @ApiImplicitParam(name = "size", value = "每页显示条数，默认 10", required = false, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "current", value = "当前页", required = false, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "String", paramType = "query")

    })
    @ApiOperation(authorizations = {@Authorization(value="Authorization")},value = "用户的钱包地址" ,httpMethod = "GET")
    @RequestMapping("/selectUserWalletUrlList")
    public ResultMap selectUserWalletUrlList(int size,int current,String userId){
        Page<Account> page=new Page<Account>(size,current);
        EntityWrapper<Account> ew = new EntityWrapper<>();
        ew.setSqlSelect("id,user_id,coin_id,user_name,real_name,coin_name,rec_addr,created");
        if (!Strings.isNullOrEmpty(userId)) {
            ew.eq("user_id", userId);
        }
        return ResultMap.getSuccessfulResult(accountService.selectListPage(page, ew));
    }

    /**
     * 虚拟币充值审
     *
     * @param accountDTO 请求参数
     * @param sysUser  当前登录用户
     * @return
     */
    @Log(value = "虚拟币充值",type = SysLogTypeEnum.UPDATE)
    @PreAuthorize("hasAuthority('account_recharge_coin_xn')")
    @PostMapping("/rechargeCoin")
    @ApiOperation(authorizations = {@Authorization(value = "Authorization")}, value = "虚拟币充值", httpMethod = "POST")
    @ApiImplicitParam(name = "accountDTO", value = "虚拟币充值参数", required = true, dataType = "AccountDTO", paramType = "body")
    @ResponseBody
    public ResultMap rechargeCoin(@RequestBody AccountDTO accountDTO, @ApiIgnore @AuthenticationPrincipal SysUser sysUser) {
        try {
            log.info("account rechargeCoin sysUser:"+sysUser);
            accountService.rechargeAmount(accountDTO, BusinessType.RECHARGE);
            return ResultMap.getSuccessfulResult("操作成功!");
        } catch (AccountException e) {
            return ResultMap.getFailureResult(1, e.getMessage());
        }
    }
}
